#ifndef _UIC_WIDGET_H
#define _UIC_WIDGET_H

namespace uic
{

class CairoUI;
class GenericEvent;
class Color;

enum WidgetEvent
    {
    WE_SELECTING_TIME,
    WE_NOT_SELECTING_TIME
    };

enum WidgetIndex  // only use this for creation
    {
    WI_STOP = 0,    WI_PLAY,        WI_PAUSE,
    WI_PLAYPAUSE,   WI_PREVIOUS,    WI_NEXT,
    WI_VOLUME,      WI_POSITION,
    WI_TIMEDISPLAY, WI_PROGRESSBAR,
    WI_ICON,        WI_COVERART,
//    WI_MAX = WI_COVERART
//    WI_VISUAL,
//    WI_MAX = WI_COVERART
    WI_TEST_CANVAS, WI_MAX = WI_TEST_CANVAS
    };

enum Justify { JUSTIFY_LEFT, JUSTIFY_CENTER, JUSTIFY_RIGHT };

// -----------------------------------------------------------------------------
//    Widget Declarations

/*   Each Widget is a bit of UI on the display.
 *
 *   -  currently active widgets are in the ui->widget_list
 *      -  inactive widgets hang out around the ui->widget_pool
 *
 *   -  widgets draw all of their state
 *      -  widgets may use the cairo context from CairoUI
 *
 *   -  the CairoUI object helps out with events in a few ways:
 *      -  if button_press returns false, button_release will not be called for
 *         that button click.
 *      -  pointer_motion / pointer_leave are used for mouse position handling.
 *         There is no pointerEnter call -- instead widgets usually set a
 *         mouseover bool when first entered.  If pointer_motion returns true,
 *         CairoUI will call pointer_leave when the pointer leaves the widget.
 */

class Widget
    {
  public:
    Widget () : next(0), prev(0)
        { timer_activate.tv_sec = 0; timer_activate.tv_usec = 0; }
    Widget *next;  /// CairoUI widget_list &
    Widget *prev;  //  widget_pool
    Widget *tail();

    double x1, y1,
           x2, y2;
    double width, height;

    bool   redraw_needed;

    WidgetIndex layout_index;
    int    layout_instance;

    virtual bool slow_redraw () { return false; }
    virtual void draw(CairoUI *ui, cairo_t *cr)=0;
    void draw_bg(CairoUI *ui, bool clip=false);
    void draw_bg_reverse(CairoUI *ui);
    virtual bool draw_background (CairoUI *ui, cairo_t *cr,
                                  double x1, double y1, double x2, double y2)
        { return false; }
    // TODO  better name?  expanding widgets stop when they hit it
    virtual bool is_physical () { return true; }

    // layout
    virtual void check_size(CairoUI *ui) {}
    virtual void configure(CairoUI *ui) {}
    virtual void disable(CairoUI *ui) {}
    virtual bool set_justify (Justify just) { return false; }
    virtual void set_option (const char *str) {}

    // UI Timer
    struct timeval timer_activate;
    void set_timer(int milliseconds);
    void clear_timer();
    virtual void timer_event(CairoUI *ui) {}
    // UI Events (received)
    virtual void event (CairoUI *ui, Event event) {}
    virtual void event (CairoUI *ui, Event event, EventData *event_Data) {}
    virtual void event (CairoUI *ui, WidgetEvent event) {}
    virtual bool key(CairoUI *ui, GenericEvent *ev) { return false; }
    virtual bool button_press(CairoUI *ui, GenericEvent *ev) { return false; }
    virtual bool button_release(CairoUI *ui, GenericEvent *ev, bool inside)
        { return false; }
    virtual bool pointer_motion(CairoUI *ui, GenericEvent *ev) { return false; }
    virtual void pointer_leave(CairoUI *ui) {}

  protected:
    bool squarify_small();
    bool squarify_big();
    };

Widget * new_widget_by_index(WidgetIndex index);

}
#endif // _UIC_WIDGET_H
